// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ExportStepTest.cs" company="">
//   
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Tests
{
    using System;
    using System.IO;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;

    using ExecutionTool.Common;
    using ExecutionTool.CopyDatabase;
    using ExecutionTool.ImportExport;
    using ExecutionTool.Profile;

    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Moq;

    [TestClass]
    public class ExportStepTest
    {
        #region Constants

        private const string ServerNamePrefix = "yj63a5jos3";

        #endregion

        #region Fields

        private Profile profile;

        #endregion

        #region Public Methods and Operators

        [TestMethod]
        public void CanStartStep()
        {
            var importExportServiceAdatperMock = new Mock<IImportExportServiceAdatper>();
            var storageAdapterMock = new Mock<IStorageAdapter>();
            var sqlAdapterMock = new Mock<ISqlAzureAdapter>();

            storageAdapterMock.Setup(adapter => adapter.CreateContainerIfNotExistAsync(It.IsAny<AzureStorageLocation>(), It.IsAny<string>())).Returns(
                Task.Factory.StartNew(
                    () =>
                        {
                            Thread.Sleep(1000);
                            return true;
                        }));
            sqlAdapterMock.Setup(adapter => adapter.GetDatabaseInfo(It.IsAny<SqlAzureLocation>(), null)).Returns(
                new SqlAzureDatabaseInfo("Web", "1GB"));

            var loggerMock = new Mock<LogWriter>();

            var step = new ExportStep(
                this.profile, importExportServiceAdatperMock.Object, storageAdapterMock.Object, sqlAdapterMock.Object, loggerMock.Object);
            step.Start();

            Assert.AreEqual(StepState.Running, step.StepState);
        }

        [TestInitialize]
        public void Setup()
        {
            this.profile = new Profile
                {
                    Name = "testprofile", 
                    Source =
                        new SqlAzureLocation
                            {
                               ServerNamePrefix = ServerNamePrefix, UserName = "username", Password = "password", DatabaseName = "databaseName" 
                            }, 
                    TargetAzureStorage = new AzureStorageLocation { StorageAccount = "storage", AccessKey = "accessKey" }, 
                };
        }

        [TestMethod]
        public void StepIsAbortableIfFromTheDatabaseCopy()
        {
            var importExportServiceAdatperMock = new Mock<IImportExportServiceAdatper>();
            var storageAdapterMock = new Mock<IStorageAdapter>();
            var sqlAdapterMock = new Mock<ISqlAzureAdapter>();
            var loggerMock = new Mock<LogWriter>();
            var step = new ExportStep(
                this.profile, 
                importExportServiceAdatperMock.Object, 
                storageAdapterMock.Object, 
                sqlAdapterMock.Object, 
                loggerMock.Object, 
                new CopyDatabaseStepInfo(new SqlAzureDatabaseInfo("Web", "1GB"), "fake_name"));

            Assert.IsTrue(step.CanAbort);
        }

        [TestMethod]
        public void StepIsNotAbortableIfFromTheOriginalDatabase()
        {
            var importExportServiceAdatperMock = new Mock<IImportExportServiceAdatper>();
            var storageAdapterMock = new Mock<IStorageAdapter>();
            var sqlAdapterMock = new Mock<ISqlAzureAdapter>();
            var loggerMock = new Mock<LogWriter>();
            var step = new ExportStep(
                this.profile, importExportServiceAdatperMock.Object, storageAdapterMock.Object, sqlAdapterMock.Object, loggerMock.Object);

            Assert.IsFalse(step.CanAbort);
        }

        [TestMethod]
        public void TestDateTimeToString()
        {
            Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-dd-HH-mm-ss"));
        }

        [TestMethod]
        public void TestGetHostEntry()
        {
            try
            {
                // Get 'IPHostEntry' object containing information like host name, IP addresses, aliases for a host.
                IPHostEntry hostInfo = Dns.GetHostEntry("bicl8auzbn.database.windows.net");
                Console.WriteLine("Host name : " + hostInfo.HostName);
                Console.WriteLine("IP address List : ");
                for (int index = 0; index < hostInfo.AddressList.Length; index++)
                {
                    Console.WriteLine(hostInfo.AddressList[index]);
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException caught!!!");
                Console.WriteLine("Source : " + e.Source);
                Console.WriteLine("Message : " + e.Message);
            }
            catch (ArgumentNullException e)
            {
                Console.WriteLine("ArgumentNullException caught!!!");
                Console.WriteLine("Source : " + e.Source);
                Console.WriteLine("Message : " + e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception caught!!!");
                Console.WriteLine("Source : " + e.Source);
                Console.WriteLine("Message : " + e.Message);
            }
        }

        [TestMethod]
        public void TestTaskChainning()
        {
            ShowMeTheThreadId("Main");
            var req = (HttpWebRequest)WebRequest.Create(new Uri("http://m.microsoft.com"));
            req.Method = "POST";

            Task<Stream>.Factory.FromAsync(req.BeginGetRequestStream, req.EndGetRequestStream, null).ContinueWith(
                t =>
                    {
                        ShowMeTheThreadId("Got request stream, begin posting");

                        using (var stream = t.Result)
                        {
                            var bytes = Encoding.ASCII.GetBytes("x=y&a=b");
                            stream.Write(bytes, 0, bytes.Length);
                        }
                    }).ContinueWith(
                        _t =>
                            {
                                ShowMeTheThreadId("End posting");
                                Console.WriteLine(_t.Status);

                                Task<WebResponse>.Factory.FromAsync(
                                    req.BeginGetResponse, req.EndGetResponse, null, TaskCreationOptions.AttachedToParent).ContinueWith(
                                        t =>
                                            {
                                                ShowMeTheThreadId("Got response, begin processing result");

                                                try
                                                {
                                                    using (var response = t.Result)
                                                    {
                                                        for (var i = 0; i < response.Headers.Count; i++)
                                                        {
                                                            Console.WriteLine("{0}: {1}", response.Headers.Keys[i], response.Headers[i]);
                                                        }
                                                    }
                                                }
                                                catch (WebException ex)
                                                {
                                                    if ((ex.Response != null) && (ex.Response is HttpWebResponse))
                                                    {
                                                        var response = ex.Response as HttpWebResponse;
                                                        Console.WriteLine("Service Error: {0} {1} ", response.StatusCode, response.StatusDescription);
                                                    }
                                                    else
                                                    {
                                                        Console.WriteLine("Service Error: {0}", ex.Message);
                                                    }
                                                }

                                                Console.WriteLine("End processing result...");
                                            }, 
                                        TaskContinuationOptions.AttachedToParent);
                            }).Wait();
            ShowMeTheThreadId("Main");
        }

        #endregion

        #region Methods

        private static void ShowMeTheThreadId(string message)
        {
            Console.WriteLine(message + ": " + Thread.CurrentThread.ManagedThreadId);
        }

        #endregion
    }
}
